--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--[[

    体力值系统

]]--
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---
    local GETTING_INTO_THE_RUNNING_COST =  10           -- 进入跑步状态消耗
    local GETTING_INTO_THE_RUNNING_COST_PER_SECOND =  5  -- 每秒消耗
    local MAX_DISTANCE = 12                                 --- 最大冲锋距离
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- 寻找最远可到达的点
    local function GetMaxPassablePoint(start_pt, end_pt)
        return TUNING.HUTAO_FNS:GetMaxPassablePoint(start_pt, end_pt, MAX_DISTANCE,0.2)
    end
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- 
    local function Spell_PreCheck(inst)
        if not inst.components.playercontroller:IsEnabled() then
            return false
        end
        if inst:HasTag("playerghost") then
            return false
        end
        if inst.replica.rider and inst.replica.rider:IsRiding() then
            return false
        end
        if inst.replica.hutao_com_physical_power:IsBlocking() then
            return false
        end
        return true
    end
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- 创建指示器
    local color = Vector3(0/255,255/255,255/255)
    local function CreateIndicator(inst)
        if not (ThePlayer and inst == ThePlayer ) then
            return
        end
        local indicator = SpawnPrefab("hutao_sfx_dotted_arrow_client")
        indicator.AnimState:SetAddColour(color.x, color.y, color.z, 0)
        indicator.AnimState:SetMultColour(color.x, color.y, color.z, 1)
        indicator.AnimState:SetBloomEffectHandle("shaders/anim.ksh")
        indicator:PushEvent("Set",{
            pt = Vector3(ThePlayer.Transform:GetWorldPosition())
        })
        --- 指示器2
        local fx = SpawnPrefab("reticule")
        fx.Transform:SetPosition(ThePlayer.Transform:GetWorldPosition())
        fx.AnimState:SetAddColour(color.x, color.y, color.z, 0)
        fx.AnimState:SetMultColour(color.x, color.y, color.z, 1)
        fx.AnimState:SetBloomEffectHandle("shaders/anim.ksh")
        indicator:ListenForEvent("onremove",function()
            fx:Remove()
        end)
        --- 定时检查指示器
        indicator:DoPeriodicTask(FRAMES*5,function()
            if inst.replica.hutao_com_physical_power:IsRunning() then
                indicator:Remove()
            end
            if inst.replica.hutao_com_physical_power:GetCurrent() < GETTING_INTO_THE_RUNNING_COST then
                indicator:Remove()
            end
            if not Spell_PreCheck(inst) then
                indicator:Remove()
            end
        end)
        --- 刷新器
        TheInput:Hutao_Add_Update_Custom_Fn(indicator,function()
            if indicator.SetRotation then
                local x,y,z = ThePlayer.Transform:GetWorldPosition()
                local mouse_pt = TheInput:GetWorldPosition()
                indicator.Transform:SetPosition(x,y,z)
                local angle = -math.deg(math.atan2(mouse_pt.z - z,mouse_pt.x - x))
                indicator:SetRotation(angle)
                mouse_pt = GetMaxPassablePoint(Vector3(x,y,z),mouse_pt)
                fx.Transform:SetPosition(mouse_pt.x,0,mouse_pt.z)
            else
                indicator:Remove()
            end
        end)
        --- 鼠标监听。
        local mouse_handle = TheInput:AddMouseButtonHandler(function(button,down)
            if down then
                if button == MOUSEBUTTON_LEFT then
                    indicator:Remove()
                    return
                end
                if button == MOUSEBUTTON_RIGHT then
                    inst.replica.hutao_com_rpc_event:PushEvent("hutao_event.getting_into_the_running",TheInput:GetWorldPosition())
                    return
                end
            end
        end)
        indicator:ListenForEvent("onremove",function()
            mouse_handle:Remove()
        end)
        return indicator
    end
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

return function(inst)
    --- 快捷键激活后执行入口。指示器创建以及技能使用。
    inst:ListenForEvent("hutao_hotkey_event.GETTING_INTO_THE_RUNNING",function(inst,_table)
        if not Spell_PreCheck(inst) then
            TheFrontEnd:GetSound():PlaySound("dontstarve/HUD/click_negative", nil, .4)
            return
        end
        local tarpos = _table and _table.tarpos
        if type(tarpos) == "table" and tarpos.x and tarpos.y and tarpos.z then
            if inst.replica.hutao_com_physical_power:GetCurrent() >= GETTING_INTO_THE_RUNNING_COST and not inst.replica.hutao_com_physical_power:IsRunning() then
                if TUNING["hutao.Config"].GETTING_INTO_THE_RUNNING_INDICATOR then
                    --- 创建指示器。
                        if inst.____GETTING_INTO_THE_RUNNING_INDICATOR and inst.____GETTING_INTO_THE_RUNNING_INDICATOR:IsValid() then
                            inst.replica.hutao_com_rpc_event:PushEvent("hutao_event.getting_into_the_running",tarpos)
                            inst.____GETTING_INTO_THE_RUNNING_INDICATOR:Remove()
                            inst.____GETTING_INTO_THE_RUNNING_INDICATOR = nil
                        else
                            inst.____GETTING_INTO_THE_RUNNING_INDICATOR = CreateIndicator(inst)
                        end
                else
                    --- 直接使用技能。
                        inst.replica.hutao_com_rpc_event:PushEvent("hutao_event.getting_into_the_running",tarpos)
                end
            else
                TheFrontEnd:GetSound():PlaySound("dontstarve/HUD/click_negative", nil, .4)
            end
        end
    end)

    if not TheWorld.ismastersim then
        return
    end
    -------------------------------------------------------
    --- 添加核心组件
        inst:AddComponent("hutao_com_physical_power")
        inst.components.hutao_com_physical_power:SetMax(100)
    -------------------------------------------------------
    --- 倍增实体
        local mult_inst = CreateEntity()
        inst:ListenForEvent("onremove",function()
            mult_inst:Remove()
        end)
        local is_running = false
        local last_pos = Vector3(0,0,0)
    -------------------------------------------------------
    -- 饥饿值消耗+体力值恢复
        inst:DoPeriodicTask(1,function()
            if inst.components.hutao_com_physical_power:IsFull() then
                inst.components.hunger.burnratemodifiers:SetModifier(mult_inst,1)
            else
                -- 饥饿值消耗倍率
                local modulus = inst.components.hutao_com_physical_power:GetModulus()
                local mult = 1+0.5*math.max(modulus,1)
                inst.components.hunger.burnratemodifiers:SetModifier(mult_inst,mult)
                -- 体力值恢复
                if not is_running and inst.components.hunger.current > 0 then
                    local delta = 4*(1+2*modulus)
                    inst.components.hutao_com_physical_power:DoDelta(delta)
                end
            end
        end)
    -------------------------------------------------------
    -- 技能激活
        local function start_running(inst)
            local modulus = inst.components.hutao_com_physical_power:GetModulus()
            inst.components.locomotor:SetExternalSpeedMultiplier(mult_inst, "getting_into_the_running",1 + modulus+0.2)
            is_running = true
            inst.components.hutao_com_physical_power:SetRunning(true)
            inst.components.hutao_com_polearm_mastery:SetRunning(true) -- 第二条net信道
        end
        local running_task = nil
        local function stop_running(inst)
            inst.components.locomotor:SetExternalSpeedMultiplier(mult_inst, "getting_into_the_running", 1)
            is_running = false
            if running_task then
                running_task:Cancel()
                running_task = nil
            end
            inst.components.hutao_com_physical_power:SetRunning(false)
            inst.components.hutao_com_polearm_mastery:SetRunning(false) -- 第二条net信道
        end
        local function assault(inst,tarpos) -- 冲锋
            -- inst.sg:GoToState("hutao_sg_spurt",{targetpos = tarpos})
            local pt = GetMaxPassablePoint(Vector3(inst.Transform:GetWorldPosition()),Vector3(tarpos.x,0,tarpos.z))
            inst.sg:GoToState("hutao_sg_spurt",{targetpos = pt})
        end
        --- 冲锋技能入口事件。RPC通过这个事件来控制冲锋
        inst:ListenForEvent("hutao_event.getting_into_the_running",function(inst,tarpos)
            if is_running then
                return
            end
            inst.components.hutao_com_physical_power:DoDelta(-GETTING_INTO_THE_RUNNING_COST)
            last_pos = Vector3(inst.Transform:GetWorldPosition())
            start_running(inst)
            running_task = inst:DoPeriodicTask(1,function()
                --- 检查体力值
                if inst.components.hutao_com_physical_power:GetCurrent() < GETTING_INTO_THE_RUNNING_COST_PER_SECOND then
                    stop_running(inst)
                    return
                end
                --- 检查是否还在移动
                local cur_pos = Vector3(inst.Transform:GetWorldPosition())
                local delta_pos = cur_pos - last_pos
                if delta_pos:LengthSq() < 0.5 then
                    stop_running(inst)
                    return
                end
                --- 消耗体力值
                inst.components.hutao_com_physical_power:DoDelta(-GETTING_INTO_THE_RUNNING_COST_PER_SECOND)
                start_running(inst)
                last_pos = cur_pos
            end)
            assault(inst,tarpos)
        end)        
    -------------------------------------------------------
    -- 强制停止奔跑
        inst:ListenForEvent("hutao_event.getting_into_the_running.force_stop",stop_running)
    -------------------------------------------------------

end